﻿// Copyright (c) 2012 Mokah Nnamezie & Andrew Cooper
// Neo4Net graph database - http://neo4net.codeplex.com
//
// This file is part of Neo4Net - a .Net port of the Neo4j graph database
//
// Neo4Net is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

namespace Neo4Net.Kernel.Impl.Core
{
    using System;
    using System.IO;
    using Neo4Net.GraphDb;
    using Neo4Net.GraphDb.Factory;
    using Neo4Net.Kernel.Impl.Nioneo.Store;
    using NUnit.Framework;

    [TestFixture]
    public class TestChangingOfLogFormat
    {
        [Test]
        public void InabilityToStartFromOldFormatFromNonCleanShutdown()
        {
            string storeDir = "target/var/oldlog";
            AbstractNeo4NetTestCase.DeleteFileOrDirectory(storeDir);
            IGraphDatabaseService db = new GraphDatabaseFactory().NewEmbeddedDatabase(storeDir);
            ITransaction tx = db.BeginTx();
            db.CreateNode();
            tx.Success();
            tx.Finish();

            Tuple<Tuple<FileInfo, FileInfo>, Tuple<FileInfo, FileInfo>> copy = TestXa.CopyLogicalLog(storeDir);
            DecrementLogFormat(copy.Item2.Item2);
            db.Shutdown();
            TestXa.RenameCopiedLogicalLog(storeDir);

            Assert.That(() => new GraphDatabaseFactory().NewEmbeddedDatabase(storeDir), Throws.Exception);
        }

        private void DecrementLogFormat(FileInfo file)
        {
            // Gotten from LogIoUtils class
            using (FileStream stream = file.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                byte[] buffer = new byte[8];
                stream.Read(buffer, 0, buffer.Length);
                long version = BitConverter.ToInt64(buffer, 0);
                long logFormatVersion = (long)((ulong)version >> 56);
                version = version & 0x00FFFFFFFFFFFFFFL;
                long oldVersion = version | (((long)logFormatVersion - 1) << 56);
                stream.Position = 0;
                Array.Clear(buffer, 0, buffer.Length);
                BitConverter.GetBytes(version);
                buffer = BitConverter.GetBytes(version);
                stream.Write(buffer, 0, buffer.Length);
            }
        }
    }
}
